package com.bigkoo.svprogresshud;

import com.bigkoo.svprogresshud.listener.OnDismissListener;
import com.bigkoo.svprogresshud.view.SVCircleProgressBar;
import com.bigkoo.svprogresshud.view.SVProgressDefaultView;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.multimodalinput.event.TouchEvent;

import java.lang.ref.WeakReference;

public class SVProgressHUD {
    private WeakReference<Context> contextWeak;
    private static final long DISMISSDELAYED = 1000;
    private SVProgressHUDMaskType mSVProgressHUDMaskType;
    private boolean isShowing;
    private boolean isDismissing;
    private ComponentContainer.LayoutConfig params;
    private int gravity = 17;
    private OnDismissListener onDismissListener;

    private ComponentContainer decorView;
    private ComponentContainer rootView;
    private SVProgressDefaultView mSharedView;

    private AnimatorProperty outAnim;
    private AnimatorProperty inAnim;


    public enum SVProgressHUDMaskType {
        None,  // 允许遮罩下面控件点击
        Clear,     // 不允许遮罩下面控件点击
        Black,     // 不允许遮罩下面控件点击，背景黑色半透明
        Gradient,   // 不允许遮罩下面控件点击，背景渐变半透明
        ClearCancel,     // 不允许遮罩下面控件点击，点击遮罩消失
        BlackCancel,     // 不允许遮罩下面控件点击，背景黑色半透明，点击遮罩消失
        GradientCancel   // 不允许遮罩下面控件点击，背景渐变半透明，点击遮罩消失
        ;
    }

    private void init() {
        params = new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        params.setMarginBottom(80);
    }


    public SVProgressHUD(Context context, ComponentContainer componentContainer) {
        this.contextWeak = new WeakReference<>(context);
        decorView = componentContainer;
        gravity = 17;
        init();
        initViews();
        decorView.setBindStateChangedListener(new Component.BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                StackLayout.LayoutConfig layoutConfig = new StackLayout.LayoutConfig();
                layoutConfig.width = decorView.getWidth();
                layoutConfig.height = decorView.getHeight();
                layoutConfig.alignment = LayoutAlignment.VERTICAL_CENTER;
                rootView.setLayoutConfig(layoutConfig);
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });

        initDefaultView();
        initAnimation();
    }

    protected void initViews() {
        Context context = contextWeak.get();
        if (context == null) return;

        LayoutScatter layoutInflater = LayoutScatter.getInstance(context);
        rootView = (ComponentContainer) LayoutScatter.getInstance(context).parse(ResourceTable.Layout_layout_svprogresshud, null, false);
    }

    protected void initDefaultView() {
        Context context = contextWeak.get();
        if (context == null) return;

        mSharedView = new SVProgressDefaultView(context);

        StackLayout.LayoutConfig layoutConfig = new StackLayout.LayoutConfig();
        layoutConfig.alignment = LayoutAlignment.VERTICAL_CENTER | LayoutAlignment.HORIZONTAL_CENTER;

        mSharedView.setLayoutConfig(layoutConfig);
    }

    protected void initAnimation() {
        if (inAnim == null)
            inAnim = getInAnimation();
        if (outAnim == null)
            outAnim = getOutAnimation();
    }

    public AnimatorProperty getInAnimation() {
        Context context = contextWeak.get();
        if (context == null) return null;

//        animatorScatter = AnimatorScatter.getInstance(context);
        return SVProgressHUDAnimateUtil.getAnimationResource(this.gravity, true);

    }

    public AnimatorProperty getOutAnimation() {
        Context context = contextWeak.get();
        if (context == null) return null;

//        animatorScatter = AnimatorScatter.getInstance(context);
        return SVProgressHUDAnimateUtil.getAnimationResource(this.gravity, false);
    }


    /**
     * show的时候调用
     */
    private void onAttached() {
        isShowing = true;
        decorView.addComponent(rootView);
        Boolean tempbool = (mSharedView.getComponentParent() != null);
        if (mSharedView.getComponentParent() != null) {
            mSharedView.getComponentParent().removeComponent(mSharedView);
        }
        rootView.addComponent(mSharedView);
    }

    /**
     * 添加这个View到Activity的根视图
     */
    private void svShow() {
        mEventHandler.removeAllEvent();
        onAttached();
    }


    public void show() {
        if (isShowing()) return;
        setMaskType(SVProgressHUDMaskType.Black);
        mSharedView.show();
        svShow();
    }

    public void showWithMaskType(SVProgressHUDMaskType maskType) {
        Boolean tempbool = (rootView.getComponentParent() != null);
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.show();
        svShow();
    }

    public void showWithStatus(String string) {
        if (isShowing()) return;
        setMaskType(SVProgressHUDMaskType.Black);
        mSharedView.showWithStatus(string);
        svShow();
    }

    public void showWithStatus(String string, SVProgressHUDMaskType maskType) {
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.showWithStatus(string);
        svShow();
    }

    public void showInfoWithStatus(String string) {
        if (isShowing()) return;
        setMaskType(SVProgressHUDMaskType.Black);
        mSharedView.showInfoWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showInfoWithStatus(String string, SVProgressHUDMaskType maskType) {
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.showInfoWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showSuccessWithStatus(String string) {
        if (isShowing()) return;
        setMaskType(SVProgressHUDMaskType.Black);
        mSharedView.showSuccessWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showSuccessWithStatus(String string, SVProgressHUDMaskType maskType) {
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.showSuccessWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showErrorWithStatus(String string) {
        if (isShowing()) return;
        setMaskType(SVProgressHUDMaskType.Black);
        mSharedView.showErrorWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showErrorWithStatus(String string, SVProgressHUDMaskType maskType) {
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.showErrorWithStatus(string);
        svShow();
        scheduleDismiss();
    }

    public void showWithProgress(String string, SVProgressHUDMaskType maskType) {
        if (isShowing()) return;
        setMaskType(maskType);
        mSharedView.showWithProgress(string);
        svShow();
    }

    public SVCircleProgressBar getProgressBar() {
        return mSharedView.getCircleProgressBar();
    }

    public void setText(String string) {
        mSharedView.setText(string);
    }

    private void setMaskType(SVProgressHUDMaskType maskType) {
        ShapeElement shapeElement = new ShapeElement();
        RgbColor[] rgbColors = new RgbColor[2];
        mSVProgressHUDMaskType = maskType;
        switch (mSVProgressHUDMaskType) {
            case None:
                shapeElement.setRgbColor(new RgbColor(00, 00, 00, 00));
                configMaskType(shapeElement, false, false);
                break;
            case Clear:
                shapeElement.setRgbColor(new RgbColor(00, 00, 00, 00));
                configMaskType(shapeElement, true, false);
                break;
            case ClearCancel:
                shapeElement.setRgbColor(new RgbColor(00, 00, 00, 00));
                configMaskType(shapeElement, true, true);
                break;
            case Black:
                shapeElement.setRgbColor(new RgbColor(00, 00, 00, 60));
                configMaskType(shapeElement, true, false);
                break;
            case BlackCancel:
                shapeElement.setRgbColor(new RgbColor(00, 00, 00, 60));
                configMaskType(shapeElement, true, true);
                break;
            case Gradient:
            case GradientCancel:
//                configMaskType(R.drawable.bg_overlay_gradient, true, false);
//                configMaskType(ResourceTable.Graphic_bg_overlay_gradient,true,false);
                shapeElement.setGradientOrientation(ShapeElement.Orientation.BOTTOM_END_TO_TOP_START);
//                shapeElement.setPath(new Path());
                rgbColors[0] = new RgbColor(ResourceTable.Color_bgColor_overlay);
                rgbColors[1] = new RgbColor(ResourceTable.Color_transparent);
                shapeElement.setRgbColors(rgbColors);
                configMaskType(shapeElement, true, false);
                break;
            default:
                break;
        }
    }


    private void configMaskType(ShapeElement shapeElement, boolean clickable, boolean cancelable) {
        rootView.setBackground(shapeElement);
        rootView.setClickable(clickable);
        setCancelable(cancelable);
    }

    /**
     * 检测该View是不是已经添加到根视图
     *
     * @return 如果视图已经存在该View返回true
     */
    public boolean isShowing() {
        return rootView.getComponentParent() != null || isShowing;
    }


    public void dismiss() {
        if (isDismissing) return;
        isDismissing = true;

        mSharedView.dismiss();
        dismissImmediately();
    }

    public void dismissImmediately() {
        mSharedView.dismiss();
        rootView.removeComponent(mSharedView);
        decorView.removeComponent(rootView);
        isShowing = false;
        isDismissing = false;
        if (onDismissListener != null) {
            onDismissListener.onDismiss(this);
        }

    }


    private void setCancelable(boolean isCancelable) {
        Component view = rootView.findComponentById(ResourceTable.Id_sv_outmost_container);

        if (isCancelable) {
            view.setTouchEventListener(onCancelableTouchListener);
        } else {
            view.setTouchEventListener(null);
        }
    }

    private static final int thread_svprogress = 1;
    public EventHandler mEventHandler = new EventHandler(EventRunner.getMainEventRunner()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            switch (event.eventId) {
                case thread_svprogress:
                    dismiss();
                default:
                    break;
            }
        }
    };

    private class LoadAnimationTask implements Runnable {

        @Override
        public void run() {
            postEvent(decorView);
        }

        protected void postEvent(ComponentContainer decorview) {
            InnerEvent innerEvent = InnerEvent.get(thread_svprogress);
            innerEvent.object = decorview;
            mEventHandler.sendEvent(innerEvent);
        }
    }


    private void scheduleDismiss() {
//        mHandler.removeCallbacksAndMessages(null);
//        mHandler.sendEmptyMessageDelayed(0, DISMISSDELAYED);
        mEventHandler.removeAllEvent();
    }

    /**
     * Called when the user touch on black overlay in order to dismiss the dialog
     */
    private final ComponentContainer.TouchEventListener onCancelableTouchListener = new Component.TouchEventListener() {
        @Override
        public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
            if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
                dismiss();
                setCancelable(false);
            }
            return false;
        }
    };


    public void setOnDismissListener(OnDismissListener listener) {
        this.onDismissListener = listener;
    }

    public OnDismissListener getOnDismissListener() {
        return onDismissListener;
    }


}
